package io.xmu.dataanalysis.service.home;

import ch.qos.logback.core.rolling.TriggeringPolicy;
import io.xmu.dataanalysis.entity.Category;
import io.xmu.dataanalysis.entity.Order;
import io.xmu.dataanalysis.entity.Shop;
import io.xmu.dataanalysis.entity.ShopDailyData;
import io.xmu.dataanalysis.model.RFM;
import io.xmu.dataanalysis.repository.*;
import io.xmu.dataanalysis.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * Created by Jim Chen at XMU on 2017/4/4.
 */

@Service
public class HomeService2 {


    private OrderRepo orderRepo;

    private ShopDailyDataRepo shopDailyDataRepo;

    private ShopRepo shopRepo;

    private CategoryRepo categoryRepo;

    private UserRepo userRepo;

    private GoodsRepo goodsRepo;

    @Autowired
    public HomeService2(OrderRepo orderRepo,
                        ShopDailyDataRepo shopDailyDataRepo,
                        ShopRepo shopRepo,
                        CategoryRepo categoryRepo,
                        UserRepo userRepo,
                        GoodsRepo goodsRepo) {
        this.orderRepo = orderRepo;
        this.shopDailyDataRepo = shopDailyDataRepo;
        this.shopRepo = shopRepo;
        this.categoryRepo = categoryRepo;
        this.userRepo = userRepo;
        this.goodsRepo = goodsRepo;
    }

    //一周之内的待办事项
    public Map<String, Integer> getBackLog(Integer shopId, String time) {
        HashMap<String, Integer> backLog = new HashMap<>();
        time = DateUtils.getNextDay(time);
        String lastWeek = DateUtils.getLastWeek(time);
//        twoWeekAgo = DateUtils.getLastWeek(twoWeekAgo);

        List<Order> orders = orderRepo.findByShopIdAndCreateTime(shopId, lastWeek, time);
        int toPay = 0;
        int paid = 0;
        int notComment = 0;
        int comment = 0;
        int complaint = 0;
        int returnBack = 0;
        //100:新建订单（未付款） 200:已付款（未发货） 300：交易成功（未评论）
        // 301：交易成功（已评论）302：（交易成功）投诉中 303：（交易成功）退货
        for (Order order : orders) {
            switch (order.getStatus()) {
                case 100:
                    toPay++;
                    break;
                case 200:
                    paid++;
                    break;
                case 300:
                    notComment++;
                    break;
                case 301:
                    comment++;
                    break;
                case 302:
                    complaint++;
                    break;
                case 303:
                    returnBack++;
                    break;
                default:
            }
        }
        backLog.put("toPay", toPay);
        backLog.put("paid", paid);
        backLog.put("notComment", notComment);
        backLog.put("commented", comment);
        backLog.put("complaint", complaint);
        backLog.put("returnBack", returnBack);
        return backLog;
    }


    public List<Map<String, Double>> getIndices(Integer shopId, String time) {
        List<Map<String, Double>> data = new ArrayList<>();
        String yesterday = DateUtils.getYesterday(time);
        ShopDailyData todayData = shopDailyDataRepo.findByShopIdAndPartition(shopId, time);
        ShopDailyData yesterdayData = shopDailyDataRepo.findByShopIdAndPartition(shopId, yesterday);
        if (todayData == null) return null;
        Map<String, Double> map = new HashMap<>();
        Integer cateId = todayData.getCateId();

        map.put("today", todayData.getSales() * 1.0);
        map.put("byApp", todayData.getPvByApp() * 1.0 / todayData.getPv() * 0.92);
        map.put("yesterday", yesterdayData.getSales() * 1.0);
        map.put("rank", shopDailyDataRepo.findSalesRankByPartitionAndCateIdAndShopId(time, cateId, shopId) * 1.0);
        data.add(map);

        map = new HashMap<>();
        map.put("today", todayData.getPayedGoodsCount() * 1.0);
        map.put("byApp", todayData.getPvByApp() * 1.0 / todayData.getPv() * 0.9);
        map.put("yesterday", yesterdayData.getPayedGoodsCount() * 1.0);
        map.put("rank", shopDailyDataRepo.findPayedGoodsCountRank(time, cateId, shopId) * 1.0);
        data.add(map);

        map = new HashMap<>();
        map.put("today", todayData.getPayedUserCount() * 1.0);
        map.put("byApp", todayData.getPvByApp() * 1.0 / todayData.getPv() * 0.95);
        map.put("yesterday", yesterdayData.getPayedUserCount() * 1.0);
        map.put("rank", shopDailyDataRepo.findPayedUserCountRank(time, cateId, shopId) * 1.0);
        data.add(map);

        map = new HashMap<>();
        map.put("today", todayData.getPv() * 1.0);
        map.put("byApp", todayData.getPvByApp() * 1.0 / todayData.getPv());
        map.put("yesterday", yesterdayData.getPv() * 1.0);
        map.put("rank", shopDailyDataRepo.findPVRank(time, cateId, shopId) * 1.0);
        data.add(map);

        map = new HashMap<>();
        map.put("today", todayData.getUv() * 1.0);
        map.put("byApp", todayData.getUvByApp() * 1.0 / todayData.getUv());
        map.put("yesterday", yesterdayData.getUv() * 1.0);
        map.put("rank", shopDailyDataRepo.findUVRank(time, cateId, shopId) * 1.0);
        data.add(map);
        return data;
    }

    public List<Object[]> getPayedUserCount(Integer shopId) {
        List<Object[]> data = new ArrayList<>();
        List<ShopDailyData> shopDailyData = shopDailyDataRepo.findByShopIdOrderByPartition(shopId);
        List<BigDecimal> averagePayedUserCount = shopDailyDataRepo.findAveragePayedUserCount(shopId);
        List<Integer> aPayedUserCount = shopDailyDataRepo.findAPayedUserCount(shopId);
        int length = shopDailyData.size();
        for (int i = 0; i < length; i++) {
            ShopDailyData dailyData = shopDailyData.get(i);
            Object[] objects = new Object[4];
            objects[0] = dailyData.getPartition();
            objects[1] = dailyData.getPayedUserCount();
            objects[2] = averagePayedUserCount.get(i);
            double sum = 0;
            for (int j = 0; j < 4; j++) {
                sum += aPayedUserCount.get(i * 8 + j);
            }
            objects[3] = sum / 4;
            data.add(objects);
        }
        return data;
    }

    public List<Object[]> getPayedGoodsCount(Integer shopId) {
        List<Object[]> data = new ArrayList<>();
        List<ShopDailyData> shopDailyData = shopDailyDataRepo.findByShopIdOrderByPartition(shopId);
        List<BigDecimal> averagePayedGoodsCount = shopDailyDataRepo.findAveragePayedGoodsCount(shopId);
        List<Integer> aPyedGoodsCount = shopDailyDataRepo.findAPayedGoodsCount(shopId);
        int length = shopDailyData.size();
        for (int i = 0; i < length; i++) {
            ShopDailyData dailyData = shopDailyData.get(i);
            Object[] objects = new Object[4];
            objects[0] = dailyData.getPartition();
            objects[1] = dailyData.getPayedGoodsCount();
            objects[2] = averagePayedGoodsCount.get(i);
            double sum = 0;
            for (int j = 0; j < 4; j++) {
                sum += aPyedGoodsCount.get(i * 8 + j);
            }
            objects[3] = sum / 4;
            data.add(objects);
        }
        return data;
    }

    public List<Object[]> getPV(Integer shopId) {
        List<Object[]> data = new ArrayList<>();
        List<ShopDailyData> shopDailyData = shopDailyDataRepo.findByShopIdOrderByPartition(shopId);
        List<BigDecimal> averagePV = shopDailyDataRepo.findAveragePV(shopId);
        List<Integer> aPV = shopDailyDataRepo.findAPV(shopId);
        int length = shopDailyData.size();
        for (int i = 0; i < length; i++) {
            ShopDailyData dailyData = shopDailyData.get(i);
            Object[] objects = new Object[4];
            objects[0] = dailyData.getPartition();
            objects[1] = dailyData.getPv();
            objects[2] = averagePV.get(i);
            double sum = 0;
            for (int j = 0; j < 4; j++) {
                sum += aPV.get(i * 8 + j);
            }
            objects[3] = sum / 4;
            data.add(objects);
        }
        return data;
    }

    public List<Object[]> getUV(Integer shopId) {
        List<Object[]> data = new ArrayList<>();
        List<ShopDailyData> shopDailyData = shopDailyDataRepo.findByShopIdOrderByPartition(shopId);
        List<BigDecimal> averageUV = shopDailyDataRepo.findAverageUV(shopId);
        List<Integer> aUV = shopDailyDataRepo.findAUV(shopId);
        int length = shopDailyData.size();
        for (int i = 0; i < length; i++) {
            ShopDailyData dailyData = shopDailyData.get(i);
            Object[] objects = new Object[4];
            objects[0] = dailyData.getPartition();
            objects[1] = dailyData.getUv();
            objects[2] = averageUV.get(i);
            double sum = 0;
            for (int j = 0; j < 4; j++) {
                sum += aUV.get(i * 8 + j);
            }
            objects[3] = sum / 4;
            data.add(objects);
        }
        return data;
    }

    public List<Object[]> getSales(Integer shopId) {
        List<Object[]> data = new ArrayList<>();
        List<ShopDailyData> shopDailyData = shopDailyDataRepo.findByShopIdOrderByPartition(shopId);
        List<BigDecimal> averageSales = shopDailyDataRepo.findAverageSales(shopId);
        List<Integer> aSales = shopDailyDataRepo.findASales(shopId);
        int length = shopDailyData.size();
        for (int i = 0; i < length; i++) {
            ShopDailyData dailyData = shopDailyData.get(i);
            Object[] objects = new Object[4];
            objects[0] = dailyData.getPartition();
            objects[1] = dailyData.getSales();
            objects[2] = averageSales.get(i);
            double sum = 0;
            for (int j = 0; j < 4; j++) {
                sum += aSales.get(i * 8 + j);
            }
            objects[3] = sum / 4;
            data.add(objects);
        }
        return data;
    }


    public List<String> getSummery(Integer shopId) {
        Shop shop = shopRepo.findOne(shopId);
        Category category = categoryRepo.findOne(shop.getCateId());
        ShopDailyData first = shopDailyDataRepo.findTheFirstOneByShopId(shopId);
        ShopDailyData last = shopDailyDataRepo.findTheLastOneByShopId(shopId);
        List<String> list = new ArrayList<>();
        list.add(String.format("%tF %tR", last.getModifiedTime(), last.getModifiedTime()));
        list.add(first.getPartition());
        list.add(last.getPartition());
        list.add(category.getName());
        list.add(shop.getPic());
        list.add(shop.getName());
        return list;
    }


    public List<Map<String, Object>> getCustomerClassification(Integer shopId) {
        String today = DateUtils.getToday();
        String from = DateUtils.getThreeWeekAgo(today);
        List<Integer> customer = orderRepo.findCustomerByShopIdAndCreateTime(shopId, from, today);
        int size = customer.size();
        double[] R = new double[size];//天数
        double[] F = new double[size];//频率
        double[] M = new double[size];//钱
        int[] ID = new int[size];//ID
        for (int i = 0; i < size; i++) {
            Integer c = customer.get(i);
            ID[i] = c;
            List<Object[]> goods = userRepo.findGoodsByIdAndShopIdAndTime(c, shopId, from, today);
            int n = goods.size();
            R[i] = ((new Date().getTime()) - ((Timestamp) (goods.get(0)[1])).getTime()) / (24 * 60 * 60 * 1000);
            double sum = 0;
            F[i] = goods.size();
            for (int j = 0; j < n; j++) {
                sum += goodsRepo.findPriceById((Integer) (goods.get(j)[0]));
            }
            M[i] = sum;
        }

        RFM rfm = new RFM();


        rfm.setR(R);
        rfm.setF(F);
        rfm.setP(M);
        rfm.setID(ID);
        rfm.progress();

        List<Map<String, Object>> classification = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("value", rfm.sets[0].size());
        map.put("name", "一级客户");
        classification.add(map);

        map = new HashMap<>();
        map.put("value", rfm.sets[1].size());
        map.put("name", "二级客户");
        classification.add(map);

        map = new HashMap<>();
        map.put("value", rfm.sets[2].size());
        map.put("name", "三级客户");
        classification.add(map);

        map = new HashMap<>();
        map.put("value", rfm.sets[3].size());
        map.put("name", "四级客户");
        classification.add(map);

        map = new HashMap<>();
        map.put("value", rfm.sets[4].size());
        map.put("name", "五级客户");
        classification.add(map);

//        for (int i = 0; i < 5; i++) {
//            System.out.format("第%d组：总人数：%d\n",i,rfm.sets[i].size());
//            System.out.format("R: %.2f F: %.2f M: %.2f\n", rfm.averageR[i], rfm.averageF[i], rfm.averageP[i]);
//
//            HashSet<RFM.Triple> set = rfm.sets[i];
//            System.out.println("     ID     R     F     M");
//            for (RFM.Triple t : set) {
//                System.out.format("%5d%5.2f%5.2f%5.2f\n",t.id,t.r,t.f,t.p);
//            }
//
//        }


        return classification;
    }


}
